Go Socket编程

最近在使用了 Golang,发现挺好用了。

前言

Golang 可以直接编译成各平台的二进制代码,并且处理网络很顺手。所以准备使用Golang来开发自己的小工具了。并且Go在大数据的处理上有很多优势,所以开始吧~~~

Golang Socket编程

网络模型回顾

Go socket编程

服务端和客户端

服务端

socket编程分为服务端编程和客户端编程,通俗的讲服务端就是等待连接的那个,客户段就是主动连接的那个。

我们先看看Golang服务端的编写,一个典型的Go 服务端的程序大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
"fmt"
"net"
)

func main() {
// 监听端口,并处理错误
l, err := net.Listen("tcp", ":8888")
if err != nil {
fmt.Println("listen error:", err)
return
}

//处理连接
for {
c, err := l.Accept()
if err != nil {
fmt.Println("accept error", err)
break
}

go handleConn(c)
}
}

//处理连接
func handleConn(c net.Conn) {
defer c.Close()
for {
//从连接中读取数据
//......
//向连接中写入数据
//....
}
}

可以看到服务端使用到的函数是Listen和Accept,好像和python没什么区别嘛,但是Golang的服务端可以处理多个连接,而不像python需要自己处理多个请求,那让我们看看python是怎么处理多个请求的吧。

客户端

说完了服务端,现在看看客服端,只有客户端和服务端连接在以起才可以形成一个完整的连接。客户端使用Dail或者DailTimeout进行连接。

阻塞Dail:

1
2
3
4
5
6
conn, err := net.Dial("tcp", "baidu.com")
if err != nil {
//处理错误
}

//处理连接

带上超时机制的Dial:

1
2
3
4
5
6
conn, err := net.DialTimeout("tcp", "baidu.com", 2 * time.Second)
if err != nil {
//处理错误
}

//处理连接

当客户端准备去连接服务端的时候,会出现以下的几种情况。

3.1.2.1 网络不可达或对方服务未启动

如果传给Dial的Addr是可以立即判断出网络不可达,或者Addr中端口对应的服务没有启动,端口未被监听,Dial会几乎立即返回错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"log"
"net"
)

func main() {
log.Println("Begin dial....")
conn, err := net.Dial("tcp", ":8888")
if err != nil {
log.Println("dial error:", err)
return
}

defer conn.Close()
log.Println("dial OK")
}

结果:

1
2
2018/03/03 00:35:31 Begin dial....
2018/03/03 00:35:32 dial error: dial tcp :8888: connectex: No connection could be made because the target machine actively refused it.

对方服务的Listen backlog满

Socket 读写

当客户端与服务端连接后,就可使用socket传输数据了。

End 参考资料

1. Go语言TCP Socket编程
2. Go网络编程——Socket